/**
 * Author: Balaram Putta
 * Date: Oct 30, 2003
 * Time: 11:10:41 AM
 */
package com.scalar.chiptrack.db;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collections;

import org.apache.commons.digester.Digester;
import org.apache.struts.util.LabelValueBean;
import com.scalar.chiptrack.utils.ConfigManager;


/**
 *
 * @author Balaram Putta
 * @version
 */
public class DBFieldValueMappings
{
    // Patterns to look for in Mappings file
    public static final String PATTERN_TABLE_TAG    = "databases/database/table";
    public static final String PATTERN_FIELD_TAG    = "databases/database/table/field";
    public static final String PATTERN_MAPPINGS_TAG = "databases/database/table/field/mapping";

    // HashMap to store fieldMap's againt table names
    private static HashMap sTableMap = new HashMap();

    // One and only object to used by this singleton
    private static DBFieldValueMappings sDBMappings = null;

    // Flag that identifies whether this class is initialized or not
    private static boolean sInitialized = false;

    // HashMap to store keyValueMap's against field names
    private HashMap mFieldMap = new HashMap();

    // HashMap to store keyValue pairs
    private HashMap mKeyValueMap = new HashMap();


    // Static initialization part
    static
    {
        init();
    }

    private DBFieldValueMappings(){}


    /**
     * Initialization method. Parses the mapping file and saves
     * the data into member variables.
     */
    public static void init()
    {
        if( sInitialized == false )
        {
            try
            {
                if( sDBMappings == null )
                {
                    sDBMappings = new DBFieldValueMappings();

                }

                Digester digester = new Digester();
                digester.push( sDBMappings );

                digester.addCallMethod( PATTERN_TABLE_TAG, "addTableMap", 1);
                digester.addCallParam( PATTERN_TABLE_TAG, 0, "name" );

                digester.addCallMethod( PATTERN_FIELD_TAG, "addFieldToTableMap", 1 );
                digester.addCallParam( PATTERN_FIELD_TAG, 0, "name" );

                digester.addCallMethod( PATTERN_MAPPINGS_TAG, "addMappingToFieldeMap", 2 );
                digester.addCallParam( PATTERN_MAPPINGS_TAG, 0, "key" );
                digester.addCallParam( PATTERN_MAPPINGS_TAG, 1, "value" );

                String mappingFileLocation = ConfigManager.getDBFieldMappingFile();
                if( ( mappingFileLocation == null ) || ( mappingFileLocation.trim().length() == 0 ) )
                {
                    throw new Exception( "Invalid DB Field Mappings file location, please check saclar.properties" );
                }

                digester.parse( mappingFileLocation ); // "d:/integ/config/db_field_value_mappings.xml"

                sInitialized = true;
            }
            catch( Throwable t )
            {
                System.out.println( "******** ERROR: Could not load DB Field Mappings" );
                t.printStackTrace();
                sInitialized = false;
            }
        }
    }

    /**
     *
     * @param tableName
     * @param fieldName
     * @param key
     * @return
     */
    public static String getMappingByKey( String tableName, String fieldName, String key )
    {
        HashMap fieldMap = ( HashMap ) sTableMap.get( tableName );
        HashMap keyValueMap = ( HashMap ) fieldMap.get( fieldName );
        return (String) keyValueMap.get( key );
    }


    /**
     *
     * @param tableName
     * @param fieldName
     * @return
     */
    public static ArrayList getAllMappings( String tableName, String fieldName )
    {
        ArrayList allMappingsList = new ArrayList();

        HashMap fieldMap = ( HashMap ) sTableMap.get( tableName );
        HashMap keyValueMap = ( HashMap ) fieldMap.get( fieldName );
        Iterator keys = keyValueMap.keySet().iterator();

        String key = null;
        String value = null;

        while( keys.hasNext() )
        {
            key = ( String ) keys.next();
            value = ( String ) keyValueMap.get( key );
            allMappingsList.add( new LabelValueBean( value, key ) );
        }

        Collections.reverse( allMappingsList );
        return allMappingsList;
    }


    /**
     * <strong>Test Method:</strong> Useed to test the functionality of this class.
     * Also serves as an example to use this class.
     * @param args
     * @throws Exception
     */
    public static void main( String[] args ) throws Exception
    {
        // Test 1
        ArrayList list = DBFieldValueMappings.getAllMappings( "PurchaseOrder", "POSTATUS" );
        Iterator itr = list.iterator();
        while( itr.hasNext() )
        {
            LabelValueBean lvBean = ( LabelValueBean ) itr.next();
            System.out.println( lvBean.getLabel() + ", " + lvBean.getValue() );
        }

        System.out.println( "\n" );

        // Test 2
        list = DBFieldValueMappings.getAllMappings( "PurchaseOrder", "DOCSTATUS" );
        itr = list.iterator();
        while( itr.hasNext() )
        {
            LabelValueBean lvBean = ( LabelValueBean ) itr.next();
            System.out.println( lvBean.getLabel() + ", " + lvBean.getValue() );
        }
    }

    /*-------------------- DIGESTER CALL BACK METHODS ------------ START -----------------------------------*/

    /**
     * Creates a HashMap and adds it to the global HashMap with key as the name of the table.
     * @param name Name of the table
     */
    public void addTableMap( String name )
    {
        //System.out.println( "table name = " + name );

        sTableMap.put( name, mFieldMap );
        mFieldMap = new HashMap();
    }


    /**
     * Creates a HashMap and adds it to the current Table HashMap with key as the name of the field.
     * @param fieldName Name of the column
     */
    public void addFieldToTableMap( String fieldName )
    {
        //System.out.println( "fieldname = " + fieldName );

        mFieldMap.put( fieldName, mKeyValueMap );
        mKeyValueMap  = new HashMap();
    }

    /**
     * Adds an entry to the keyValueMap.
     * @param key
     * @param value
     */
    public void addMappingToFieldeMap( String key, String value )
    {
        //System.out.println( "key = " + key + ", value = " + value );
        mKeyValueMap.put( key, value );
    }

    /*-------------------- DIGESTER CALL BACK METHODS ------------- END -----------------------------------*/

}